﻿using System;
using System.Windows.Forms;
using System.Collections;
using System.Data;
using System.Drawing;
using System.Diagnostics;
using System.Threading;

namespace DataUpload
{
    public partial class FrmProgress : Form
    {
        private MainForm _container = null;
        private string[] _seps = { "," };
        private string _transName;
        private DateTime _startUpload;
        private int _currentTextIndex;
        private bool _cancelled = false;
        
        public FrmProgress()
        {
            InitializeComponent();
        }

        public FrmProgress(MainForm container)
        {
            _container = container;
            InitializeComponent();
            btnCommit.Visible = false;
            btnRollback.Visible = false;
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            this.Hide();
            _container.frmMapping.Show();
            _container.frmMapping.Focus();
        }

        private void btnUpload_Click(object sender, EventArgs e)
        {
            if (btnUpload.Text == "Upload")
            {
                btnUpload.Text = "Cancel";
                btnBack.Enabled = false;
                btnClose.Enabled = false;
                rteProgress.Clear();
                lblEstimatedTime.Text = "Estimating remaining time...";
                _cancelled = false;

                _transName = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt");
                _startUpload = DateTime.Now;
                string action = "";
                try
                {
                    action = "Opening connection";
                    _container.frmConnect.dbc.Open();
                    action = "Start a transaction: " + _transName;
                    _container.frmConnect.dbc.BeginTransaction("ReadCommitted", _transName);
                    action = "Start mapping";
                    StartMapping();
                    action = "Start uploading";
                    Upload();
                }
                catch (Exception exc)
                {
                    DBConnection.MyDebugClass.LogThis(action, exc);
                    rteProgress.SelectionColor = Color.Red;
                    rteProgress.SelectedText = exc.Message + Environment.NewLine;
                    //rteProgress.AppendText(exc.StackTrace);
                    btnUpload_Click(sender, e);
                }
            }
            else if (btnUpload.Text == "Cancel")
            {
                StopEverything();
                btnRollback_Click(sender, e);
                _cancelled = true;

                rteProgress.SelectionColor = Color.Red;
                rteProgress.SelectedText = Environment.NewLine + "Uploading progress has been cancelled!";
            }
            else if (btnUpload.Text == "View report")
            {
                this.Hide();
                if (_container.frmSummary == null)
                    _container.frmSummary = new FrmSummary(_container);

                _container.frmSummary.Show();
                _container.frmSummary.Focus();
            }
        }

        private void StopEverything()
        {
            SortedList targetFiles = _container.frmMapping.parsedFiles;
            foreach (ReadFiles.ParsedFile f in targetFiles.Values)
                f.Stop();
        }

        private void StartMapping()
        {
            System.Windows.Forms.Timer tmpTimer = new System.Windows.Forms.Timer();
            tmpTimer.Interval = 200;
            tmpTimer.Tick += new EventHandler(tmpTimer_Tick);
            SortedList targetFiles = _container.frmMapping.parsedFiles;
            SortedList maps = _container.frmMapping.maps;
            string targetFilePath;
            ReadFiles.ParsedFile.MapStatus status;
            DataTable failedRow;
            tmpTimer.Start();
            for (int i = 0; i < targetFiles.Count; i++)
            {
                targetFilePath = targetFiles.GetKey(i).ToString();

                ArrayList sourceColumns = new ArrayList();
                ArrayList targetColumns = new ArrayList();
                ArrayList targetType = new ArrayList();
                DataGridView source = ((MappingCtrl)maps[targetFilePath]).dgvMapping;
                foreach (DataGridViewRow row in source.Rows)
                {
                    sourceColumns.Add(row.Cells[0].Value);
                    targetColumns.Add(row.Cells[1].Value);
                    targetType.Add(row.Cells[2].Value);
                }

                rteProgress.AppendText("Mapping " + targetFilePath + ". Please wait... ");
                Application.DoEvents();
                if (((ReadFiles.ParsedFile)targetFiles.GetByIndex(i)).DoMapping(sourceColumns,
                    targetColumns, targetType, 10, out status, out failedRow) == true)
                {
                    rteProgress.AppendText("Done" + Environment.NewLine);
                }
                else
                {
                    rteProgress.SelectionColor = Color.Red;
                    rteProgress.SelectedText = "Failed" + Environment.NewLine;
                    rteProgress.AppendText("Reason: " + status.ToString() + Environment.NewLine);
                    rteProgress.AppendText("\t" + ReadFiles.ParsedFile.GetStatusDescription(status) + Environment.NewLine);
                    rteProgress.AppendText("Failed row(s): " + Environment.NewLine);
                    foreach (DataRow r in failedRow.Rows)
                        rteProgress.AppendText("\t+ " + r[0].ToString() + Environment.NewLine);
                }
            }
            tmpTimer.Stop();
            tmpTimer.Dispose();
        }

        void tmpTimer_Tick(object sender, EventArgs e)
        {
            Application.DoEvents();
        }

        private void Upload()
        {
            progressFile.Minimum = 0;
            progressFile.Maximum = 100;
            progressFile.Value = 0;

            progressTotal.Minimum = 0;
            progressTotal.Maximum = 100 * _container.frmMapping.parsedFiles.Count;
            progressTotal.Value = 0;

            SortedList targetFiles = _container.frmMapping.parsedFiles;
            string targetFilePath;
            for (int i = 0; i < targetFiles.Count; i++)
            {
                targetFilePath = targetFiles.GetKey(i).ToString();
                _currentTextIndex = rteProgress.TextLength - 1;
                ((ReadFiles.ParsedFile)targetFiles.GetByIndex(i)).RowsInsertedEvent += new DataUpload.ReadFiles.RowsInsertedEventHandler(FrmProgress_RowsInsertedEvent);
                ((ReadFiles.ParsedFile)targetFiles.GetByIndex(i)).NotifyAfter = 10;
                lblFileUploading.Text = "Uploading " + targetFilePath;
                progressFile.Value = 0;
                ((ReadFiles.ParsedFile)targetFiles.GetByIndex(i)).StartUpload(ref _container.frmConnect.dbc);
            }

            if (_cancelled == false)
            {
                btnCommit.Visible = true;
                btnRollback.Visible = true;
                btnUpload.Text = "View report";
                btnUpload.Enabled = false;
                rteProgress.AppendText("Time elapsed: " + (DateTime.Now - _startUpload).ToString());

                progressFile.Value = 100;
                progressTotal.Value = progressTotal.Maximum;
            }
        }

        private void FrmProgress_RowsInsertedEvent(object sender, DataUpload.ReadFiles.RowsInsertedEventArgs e)
        {
            if (rteProgress.TextLength - 1 > _currentTextIndex)
            {
                rteProgress.Select(_currentTextIndex + 1, rteProgress.TextLength - _currentTextIndex);
                rteProgress.SelectedText = "";
            }

            rteProgress.SelectionColor = Color.Blue;
            rteProgress.SelectedText = e.Status + Environment.NewLine;
            rteProgress.AppendText("\t+ Inserted: " + e.RowsInserted + " row(s)" + Environment.NewLine);
            rteProgress.AppendText("\t+ Failed: ");
            rteProgress.SelectionColor = Color.Red;
            rteProgress.SelectedText = e.RowsFailed.ToString();
            rteProgress.AppendText(" row(s)" + Environment.NewLine);

            int percent = ((ReadFiles.ParsedFile)sender).PercentCompleted;
            progressTotal.Value += percent - progressFile.Value;
            progressFile.Value = percent;
            lblFilePercent.Text = progressFile.Value.ToString() + "%";
            lblTotalPercent.Text = ((int)progressTotal.Value * 100 / progressTotal.Maximum).ToString() + "%";

            if (progressTotal.Value != 0)
            {
                TimeSpan timespan1 = DateTime.Now - _startUpload;
                TimeSpan timespan2 = new TimeSpan(timespan1.Ticks);
                int times = 1 + (progressTotal.Maximum - progressTotal.Value) / progressTotal.Value;
                for (int i = 0; i < times; i++)
                    timespan2 = timespan2.Add(timespan1);
                string estimatedTime = "";
                if (timespan2.Days > 0)
                    estimatedTime += timespan2.Days + " day(s) ";
                if (timespan2.Hours > 0)
                    estimatedTime += timespan2.Hours + " hour(s) ";
                if (timespan2.Minutes > 0)
                    estimatedTime += timespan2.Minutes + " minute(s) ";
                if (timespan2.Seconds > 0)
                    estimatedTime += timespan2.Seconds + " second(s) ";
                lblEstimatedTime.Text = estimatedTime + " remaining";
            }
            Application.DoEvents();
        }

        private void FrmProgress_VisibleChanged(object sender, EventArgs e)
        {
            this.Focus();
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            StopEverything();
            _container.Close();
        }

        private void btnCommit_Click(object sender, EventArgs e)
        {
            _container.frmConnect.dbc.Commit(_transName);
            _container.frmConnect.dbc.Close();

            btnCommit.Visible = false;
            btnRollback.Visible = false;
            btnUpload.Enabled = true;
            btnClose.Enabled = true;
        }

        private void btnRollback_Click(object sender, EventArgs e)
        {
            _container.frmConnect.dbc.Rollback(_transName, true);
            _container.frmConnect.dbc.Close();

            btnUpload.Text = "Upload";
            btnUpload.Enabled = true;
            btnBack.Enabled = true;
            btnClose.Enabled = true;
            progressFile.Value = 0;
            lblFilePercent.Text = "0%";
            progressTotal.Value = 0;
            lblTotalPercent.Text = "0%";
            rteProgress.Clear();

            btnCommit.Visible = false;
            btnRollback.Visible = false;
        }
    }
}
